package cn.hd01.thymeleaf;

import cn.hd01.repository.entity.Permissions;
import cn.hd01.service.PermissionsService;
import cn.hd01.web.util.WebHelper;
import org.thymeleaf.Arguments;
import org.thymeleaf.dom.Element;
import org.thymeleaf.processor.ProcessorResult;
import org.thymeleaf.processor.attr.AbstractAttrProcessor;
import org.thymeleaf.spring4.context.SpringWebContext;
import org.thymeleaf.util.StringUtils;
import org.thymeleaf.util.Validate;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author cyb
 * @date 2017/5/25.
 */
public class HasPermissionProcessor extends AbstractAttrProcessor {
    private static final String DELIMITER = ",";

    protected HasPermissionProcessor() {
        super("hasPermission");
    }

    @Override
    public int getPrecedence() {
        return 0;
    }


    @Override
    protected ProcessorResult processAttribute(Arguments arguments, Element element, String attributeName) {
        final String attributeValue = element.getAttributeValue(attributeName);

        Validate.notEmpty(attributeValue, "HasPermissionProcessor permission cannot be null");
        final String[] values = StringUtils.split(attributeValue, DELIMITER);

        SpringWebContext context = (SpringWebContext) arguments.getContext();

        PermissionsService service = context.getApplicationContext().getBean(PermissionsService.class);
        List<Permissions> permissionsTree = service.findPermissionsCached(WebHelper.currentUser().getRoleId());

        Set<String> keys = new HashSet<>();
        for (Permissions p : permissionsTree) {
            if (!StringUtils.isEmpty(p.getKey())) {
                keys.add(p.getKey());
            }
        }

        boolean hasAllPermission = true;
        for (String value : values) {
            if (!keys.contains(value.trim())) {
                hasAllPermission = false;
                break;
            }
        }

        if (!hasAllPermission) {
            element.clearChildren();
            element.getParent().removeChild(element);
            return ProcessorResult.OK;
        }

        element.removeAttribute(attributeName);
        return ProcessorResult.OK;
    }
}
